/*
 * Copyright 2013 NJUT  qixiaobo. All rights reserved.
 */
package com.fujitsu.nanjing.tieba.security;
/**
 *  MySecurityMetadataSource.java
 *
 * @author Administrator
 */

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntPathRequestMatcher;
import org.springframework.security.web.util.RequestMatcher;

import com.fujitsu.nanjing.tieba.ibator.CoreGroup;
import com.fujitsu.nanjing.tieba.service.GroupService;

//1 加载资源与权限的对应关系  

/**
 * 该过滤器的主要作用就是通过spring著名的IoC生成securityMetadataSource。
 * securityMetadataSource相当于本包中自定义的MyInvocationSecurityMetadataSourceService。
 * 该MyInvocationSecurityMetadataSourceService的作用提从数据库提取权限和资源，装配到HashMap中，
 * 供Spring Security使用，用于权限校验。
 * 
 * @author qixiaobo
 */
public class MySecurityMetadataSource
		implements
			FilterInvocationSecurityMetadataSource {
	// 由spring调用
	public MySecurityMetadataSource(GroupService groupService) {
		this.groupService = groupService;
		loadResourceDefine();
	}

	private final GroupService groupService;
	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
	private RequestMatcher pathMatcher;
	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return new ArrayList<ConfigAttribute>();
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}
	// 加载所有资源与权限的关系
	private void loadResourceDefine() {
		resourceMap = new LinkedHashMap<String, Collection<ConfigAttribute>>();
		List<CoreGroup> groups = groupService.findAllGroups();
		resourceMap = putAnonymousResource(resourceMap, groups);
		Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
		for (CoreGroup group : groups) {
			String groupName = group.getGroupname();
			if (groupName.equals("游客")) {
				continue;
			}
			ConfigAttribute ca = new SecurityConfig(groupName);
			atts.add(ca);
			// 此处硬编码可以考虑创建表
		}
		resourceMap.put("/**", atts);
	}
	// 返回所请求资源所需要的权限
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		for (Map.Entry<String, Collection<ConfigAttribute>> entry : resourceMap
				.entrySet()) {
			String resURL = entry.getKey();
			pathMatcher = new AntPathRequestMatcher(resURL);
			if (pathMatcher.matches(((FilterInvocation) object).getRequest())) {
				Collection<ConfigAttribute> returnCollection = entry.getValue();
				return returnCollection;
			}
		}
		return null;
	}

	private Map<String, Collection<ConfigAttribute>> putAnonymousResource(
			Map<String, Collection<ConfigAttribute>> resourceMap,
			List<CoreGroup> groups) {
		Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
		for (CoreGroup group : groups) {
			String groupName = group.getGroupname();
			ConfigAttribute ca = new SecurityConfig(groupName);
			atts.add(ca);
		}
		ConfigAttribute ca = new SecurityConfig("ROLE_ANONYMOUS");
		atts.add(ca);
		resourceMap.put("/", atts);
		resourceMap.put("/forum/boards/*", atts);
		resourceMap.put("/forum/boards/**/pages/*", atts);
		resourceMap.put("/forum/sections/**", atts);
		resourceMap.put("/topics/**/pages/*", atts);
		resourceMap.put("/topics/*", atts);
		resourceMap.put("/forum/stat/baseinfo", atts);
		resourceMap.put("/help", atts);
		resourceMap.put("/userlist", atts);
		resourceMap.put("/userlist/pages/*", atts);
		resourceMap.put("/help/*", atts);
		resourceMap.put("/findPwd", atts);
		resourceMap.put("/findPwd/**", atts);
		resourceMap.put("/changePwd", atts);
		resourceMap.put("/myforum/checkUserId", atts);
		resourceMap.put("/myforum/checkEmail", atts);
		resourceMap.put("/myforum/checkVerifyCode", atts);
		resourceMap.put("/myforum/register", atts);
		resourceMap.put("/myforum/login", atts);
		return resourceMap;

	}

}